/**
 * ie8及以下浏览器对部分原生方法的补充实现
 */
(function (window, undefined) {

    /* =================================
     *  window.String
     * ================================= */

    /**
     * 扩展ie低版本下的startWith方法
     * @param {string} str
     * @returns
     */
    String.prototype.startsWith = function (str) {
        if (str == null || str == "" || this.length == 0 || str.length > this.length)
            return false;
        if (this.substr(0, str.length) == str) {
            return true;
        } else {
            return false;
        }
    };

    /**
     * 扩展ie低版本下的endsWith方法
     * @param {string} str
     * @returns
     */
    String.prototype.endsWith = function (str) {
        if (str == null || str == "" || this.length == 0 || str.length > this.length)
            return false;
        if (this.substr(str.length - 1, str.length) == str) {
            return true;
        } else {
            return false;
        }
    };

    /* =================================
     *  window.Array
     * ================================= */

    /**
     * 扩展ie低版本下的contains方法
     * @param {any} item
     * @returns
     */
    Array.prototype.contains = function (item) {
        return RegExp("\\b" + item + "\\b").test(this);
    };

    /**
     * 扩展ie低版本下的indexOf的方法
     * @param {any} searchElement
     * @param {number} fromIndex
     * @returns
     */
    Array.prototype.indexOf = function (searchElement, fromIndex) {
        var index = -1;
        fromIndex = fromIndex * 1 || 0;
        for (var k = 0, length = this.length; k < length; k++) {
            if (k >= fromIndex && this[k] === searchElement) {
                index = k;
                break;
            }
        }
        return index;
    };

    /**
     * 扩展ie低版本下的lastIndexOf的方法
     * @param {any} searchElement
     * @param {number} fromIndex
     * @returns
     */
    Array.prototype.lastIndexOf = function (searchElement, fromIndex) {
        var index = -1, length = this.length;
        fromIndex = fromIndex * 1 || length - 1;

        for (var k = length - 1; k > -1; k -= 1) {
            if (k <= fromIndex && this[k] === searchElement) {
                index = k;
                break;
            }
        }
        return index;
    };

    /**
     * 扩展ie低版本下的forEach的方法
     * @param {function} callback
     * @param {object} thisArg
     * @returns
     */
    Array.prototype.forEach = function (callback, thisArg) {
        for (var k = 0, length = this.length; k < length; k++) {
            if (typeof callback === "function" && Object.prototype.hasOwnProperty.call(this, k)) {
                callback.call(thisArg, this[k], k, this);
            }
        }
    };

    /**
     * 扩展ie低版本下的map的方法
     * @param {function} callback
     * @param {object} thisArg
     * @returns
     */
    Array.prototype.map = function (callback, thisArg) {
        var arr = [];
        if (typeof callback === "function") {
            for (var k = 0, length = this.length; k < length; k++) {
                arr.push(callback.call(thisArg, this[k], k, this));
            }
        }
        return arr;
    };

    /**
     * 扩展ie低版本下的filter的方法
     * @param {function} callback
     * @param {object} thisArg
     * @returns
     */
    Array.prototype.filter = function (callback, thisArg) {
        var arr = [];
        if (typeof callback === "function") {
            for (var k = 0, length = this.length; k < length; k++) {
                callback.call(thisArg, this[k], k, this) && arr.push(this[k]);
            }
        }
        return arr;
    };

    /**
     * 扩展ie低版本下的some的方法
     * @param {function} callback
     * @param {object} thisArg
     * @returns
     */
    Array.prototype.some = function (callback, thisArg) {
        var passed = false;
        if (typeof callback === "function") {
            for (var k = 0, length = this.length; k < length; k++) {
                if (passed === true) break;
                passed = !!callback.call(thisArg, this[k], k, this);
            }
        }
        return passed;
    };

    /**
     * 扩展ie低版本下的every的方法
     * @param {function} callback
     * @param {object} thisArg
     * @returns
     */
    Array.prototype.every = function (callback, thisArg) {
        var passed = true;
        if (typeof callback === "function") {
            for (var k = 0, length = this.length; k < length; k++) {
                if (passed === false) break;
                passed = !!callback.call(thisArg, this[k], k, this);
            }
        }
        return passed;
    };

    /**
     * 扩展ie低版本下的reduce的方法
     * @param {function} callback
     * @param {object} initialValue 初始值
     * @returns
     */
    Array.prototype.reduce = function (callback, initialValue) {
        var previous = initialValue, k = 0, length = this.length;
        if (typeof initialValue === "undefined") {
            previous = this[0];
            k = 1;
        }

        if (typeof callback === "function") {
            for (k; k < length; k++) {
                this.hasOwnProperty(k) && (previous = callback(previous, this[k], k, this));
            }
        }
        return previous;
    };

    /**
     * 扩展ie低版本下的reduceRight的方法
     * @param {function} callback
     * @param {object} initialValue 初始值
     * @returns
     */
    Array.prototype.reduceRight = function (callback, initialValue) {
        var length = this.length, k = length - 1, previous = initialValue;
        if (typeof initialValue === "undefined") {
            previous = this[length - 1];
            k--;
        }
        if (typeof callback === "function") {
            for (k; k > -1; k -= 1) {
                this.hasOwnProperty(k) && (previous = callback(previous, this[k], k, this));
            }
        }
        return previous;
    };


})(typeof window === 'object' ? window : this);
